<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="coinfaces">

        <title>更抽象地思考</title>

    <link rel="stylesheet" href="../../theme/css/style.css">
    <link rel="stylesheet" href="../../theme/css/pygments.css">



</head>

<body>
    <div class="content">
<h1>更抽象地思考</h1>    <p>
        under
            <a href="../../tags/reading/">reading</a>
            <a href="../../tags/programming/">programming</a>
    </p>
    <p>
        in <a href="../../categories/thought/">thought</a>
    </p>
    <p>Published: 2016-10-12</p>


    <p>最近读了三篇文章，第一篇是<a class="reference external" href="http://www.joelonsoftware.com/">Joel Spolsky</a>的<a class="reference external" href="http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html">The Perils of JavaSchools</a>，译文：<a class="reference external" href="http://www.ruanyifeng.com/blog/2008/12/the_perils_of_javaschools.html">Java语言学校的危险性</a>。</p>
<p>文章大意如下：</p>
<ul class="simple">
<li>作者小时候用穿孔卡片编程，当他开始面试新人时，绝大部分人用C解决问题，现在越来越多的人使用Java。</li>
<li>作者认为计算机科学里有两样东西很多人都没有完全理解，指针和递归，它们虽然对思维要求较高，但可以筛选掉对不感兴趣或不适合编程的学生。</li>
<li>在计算机业界需求和高淘汰率的压力下，越来越多的学校选择用Java教学，淘汰率降低，更多的学生毕业，经费预算增加，皆大欢喜。</li>
<li>虽然大部分情况下用不到指针和函数式编程<a class="footnote-reference" href="#id6" id="id5">[1]</a>，但它们在某些重要的应用中（比如内核和并行计算）举足轻重。</li>
<li>更重要的是指针和递归对思维的训练是一般Java教学不能比拟的，Java主打的面向对象设计对思维的训练比记忆名词高明不了多少。</li>
<li>因此Java作为高校计算机学科的教学语言是比较失败的，因为高校不是职业培训学校，他们应该教给学生更为根本的立足之道。</li>
<li>Java教学者们还试图更进一步，从Java中提炼一个更适合教学的语言“子集”，与其这样做，不如直接用Scheme教学，聪明的学生只需10分钟就能学会它，剩余的时间可以教他们更有意义的东西，更何况前者还要免不了向学生解释Java里<tt class="docutils literal">int</tt>和<tt class="docutils literal">Integer</tt>的区别。</li>
</ul>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id5">[1]</a></td><td>作者开始说的是递归，这里说的是函数式编程，递归可以看成函数式编程的代表特性，但其使用不局限于函数式编程</td></tr>
</tbody>
</table>
<p>接着又读了文中提到的<a class="reference external" href="http://www.paulgraham.com/">Paul Graham</a> 的<a class="reference external" href="http://www.paulgraham.com/avg.html">Beating the Averages</a>，作者分析了以前的创业项目Viaweb之所以成功，是因为他们比对手采用了更高级的编程语言。</p>
<p>文章大意如下：</p>
<ul class="simple">
<li>1995年夏天，作者和他的朋友Robert Morris开始了一个创业项目，与之前的软件项目的不同是，它运行在服务器上，用网页作为用户界面（现在用户非常熟悉的网页应用），另一个不同寻常之处是这个项目是用Lisp写成的。</li>
<li>Lisp是Viaweb的“秘密武器”<ul>
<li>事实1：创业项目不像大企业，仅达到平均水平不满足生存条件，只有超越大部分对手才有可能活下来。</li>
<li>事实2：在服务器上运行的程序可以用任何语言写成，特别是在操作系统和编译器的源码都可公开获得的情况下，很少有人意识到这个问题，因为开发平台应用的时候，一般会采用和该平台一致的语言进行开发。</li>
<li>基于这两个事实，在其它条件相同的情况下，应该选用最高级的语言来写这个项目，因为这样可以用更少的资源进行更快地开发。</li>
</ul>
</li>
<li>为什么Lisp是最高级的语言<ul>
<li>编程语言都是图灵等价的，评价语言的高级程度不能仅考虑这一个要素，一般认为机器语言是低级语言，所有高级语言则相差不大，但这里存在一个悖论，即使高级语言，也有程度的差别。</li>
<li>首先粗略地定义一种语言比另一种语言高级即要在后者中实现前者中的某项特性，除了用后者实现前者之外别无他法。比如要在Fortran（旧版本）里实现递归，不是写一个库函数就可以做到的。</li>
<li>如果高级语言确实有程度区别，为什么大部分人都认为它们没有差别呢，假想存在一种语言Blub，落在所有高级语言中间，Blub程序员往更低级的一端看，则很容易知道这些语言比Blub低级，因为Blub语言的某些特性，它们没有。但如果Blub程序员往更高级的一端看，则不那么容易分辨更高级的语言和Blub的差别，因为其思维方式被Blub限制了。于是大部分程序员看来，有低级语言，但高级语言都差不多，只有使用最高级语言的程序员才会清楚地看到编程语言之间的这些差别。</li>
<li>Lisp宏是独一无二的，其它语言即使存在宏，也和Lisp不同，因此Lisp是最高级的语言。</li>
<li>在Viaweb里，宏大概占有20%-25%的代码，其存在不是因为炫技，而是却有需要，想想这些宏完成了其它语言中很难做到的工作，也许这导致了Viaweb实现了对手产品中没有的功能。</li>
</ul>
</li>
<li>给创业者的建议<ul>
<li>作者无意说服任何不使用Lisp的程序员来使用Lisp，而是劝说已经在使用Lisp的程序员不要灰心，用自己的优势来碾压对手。</li>
<li>另一条建议是用招募通知来评价对手，工作描述中的“IT味”越浓，就越不用担心，但如果对手招募Perl或Python程序员，就要小心了，如果是招募Lisp程序员，要特别小心。</li>
</ul>
</li>
</ul>
<p>Paul Graham还给出了这篇文章的素材来源：<a class="reference external" href="http://ep.yimg.com/ty/cdn/paulgraham/bbnexcerpts.txt">一篇演讲稿摘录</a>，里面介绍了Lisp特性给Viaweb中的应用：</p>
<ul class="simple">
<li>前提是服务端后台应用可以用任何语言写成。</li>
<li>Lisp非常适合渐进式的开发（Incremental Development），Viaweb编辑器就是这样从一个120行的示例程序增长为一个25000行的应用。</li>
<li>Lisp交互式界面有利于快速修复Bug，一个快速修复的Bug有时甚至让用户觉得遇到的Bug其实是一种错觉。</li>
<li>Lisp宏很适合生成HTML，Viaweb实现了嵌入式语言Rtml来做这件事，它主要有以下作用：<ul>
<li>高级用户的进阶使用方式。</li>
<li>根据用户使用Rtml的方式来改进Viaweb的默认模板存在不足。</li>
<li>Rtml使软件设计更加简洁。</li>
</ul>
</li>
<li>Lisp闭包被用来维护用户会话中的环境参数，使得用户操作能影响后续访问。比如当用户从选项页面选择一些参数后返回原页面时，所选参数能立即反馈在该页面上，就像进行了函数调用一样。</li>
</ul>
<p>Paul Graham的两篇文章主要分析了用Lisp进行软件开发的好处，也确实如他所说，Lisp宏是独特的，因为其他好处只要是支持函数式编程的语言，比如Python或Javascript都能提供。因此这两篇文章留给我最主要的就是对Lisp宏的疑惑和好奇，有些语言（如C++和Ruby）的设计者提到他们可以避免了在语言中引入宏，但究竟Lisp宏是“强大”的还是“邪恶”的，只有用的人才知道。</p>
<p>给我留下最深印象的还是第一篇文章中的一段话：</p>
<blockquote>
But what about the CS mission of CS departments? They're not vocational schools! It shouldn't be their job to train people to work in industry. That's for community colleges and government retraining programs for displaced workers, they will tell you. They're supposed to be giving students the fundamental tools to live their lives, not preparing them for their first weeks on the job. Right?</blockquote>
<p>即我们不能止步于眼前或未来用于求生的技能，掌握其思想才是更重要的，特别是在新/旧工作不断涌现/消失的现代社会。用一门编程语言产生可以使用的软件，不能算会程序设计，对大部分人而言，程序设计是从使用一门编程语言中产生，又独立（第一位程序员<a class="reference external" href="https://en.wikipedia.org/wiki/Ada_Lovelace">Ada</a>去世一个世纪后第一台计算机<a class="reference external" href="https://en.wikipedia.org/wiki/ENIAC">ENIAC</a>才诞生）于任何一门编程语言的能力。这种能力的获得，除了靠程序积累，更要靠有针对性的思维训练。</p>
<p>这里不得不提到文中建议查看的<a class="reference external" href="https://mitpress.mit.edu/sicp/full-text/book/book.html">Structure and Interpretation of Computer Programs</a>这本书。看了目录之后就惊了，原来编程可以这么学！但马上就反问自己，难道不应该这么学吗？回想以前，真是浪费了太多的时间。写到这里，又想起萧井陌写过一个“编程入门指南”，点开<a class="reference external" href="https://zhuanlan.zhihu.com/p/19959253">最新版本</a>一看，这本书赫然出现在入门阶段，MIT CS600等教程之后，安排的顺序非常合理。是的，这是正确的前进方向，小小的一步，等不及要出发了。</p>
<p>（完）</p>

    </div>
<nav class="nav sidebar">
    <div class="siteinfo">
        <div class="sitename"><a href="../..">coinfaces</a></div>
        <div class="tagline">Another Side of Life</div>
    </div>

        <a href="../../categories/">categories</a>
        <a href="../..">&larr; Home</a>
</nav><footer class="footer">
    <span>
        &copy; jpli &middot;
        under <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA 4.0</a>
    </span>
    |
    <span>
        Powered by:
        <a href="http://blog.getpelican.com/">Pelican</a>
    </span>
</footer></body>
</html>